package com.scope;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 自定义本地线程级别的bean作用域，不同的线程中对应的bean实例是不同的，同一个线程中同名的bean是同一个实例
 */
public class ThreadScope implements Scope {
	public static final String THREAD_SCOPE = "thread";

	private ThreadLocal<Map<String, Object>> beanMap = new ThreadLocal<Map<String, Object>>() {
		@Override
		protected Map<String, Object> initialValue() {
			return new HashMap<>();
		}
	};

	/**
	 * todo 其实核心部分在这里，讲讲吧，context.getBeanFactory().registerScope(ThreadScope.THREAD_SCOPE,new ThreadScope());
	 * 1.上面通过把自定义地scope放入到scope的Map中，然后xml定义scope则是决定AbstractBeanFactory.doGetBean的scope走哪里，
	 * 2.调用到自定义scope的scope.get（）方法，也就是下面这个，当没有bean的时候调用传进来的函数式接口则会执行外部的lambda表达式方法了
	 *
	 * @param name
	 * @param objectFactory
	 * @return
	 */
	@Override
	public Object get(String name, ObjectFactory<?> objectFactory) {
		Object bean = beanMap.get().get(name);
		System.out.println("bean" + bean);
		if (Objects.isNull(bean)) {
			System.out.println("objectFactory.getObject()");
			bean = objectFactory.getObject();
			beanMap.get().put(name, bean);
		}
		return bean;
	}

	@Override
	public Object remove(String name) {
		return beanMap.get().remove(name);
	}

	@Override
	public void registerDestructionCallback(String name, Runnable callback) {
		System.out.println(name);
	}

	@Override
	public Object resolveContextualObject(String key) {
		return null;
	}

	@Override
	public String getConversationId() {
		return Thread.currentThread().getName();
	}
}
